"""售货和聊天模块"""

import time
from random import choices, random

from prettytable import PrettyTable
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.wait import WebDriverWait

from shopee.browser import browser, wait
from shopee.logger import logger
from shopee.utils import *
from shopee.visitlocal import TxtControl
from shopee.config import CF

SEARCH_URL = 'https://seller.shopee.com.my/portal/sale/shipment?type=toship'
DETECTION_COUNT = 0


def into_shipping(func):
    """进入和退出shipping页"""

    def inner(*args, **kwargs):
        ok = False
        _, message_dict, order_id = args
        divs_xpath = '//div[@class="list-tabs"]//div[@class="shopee-tabs__nav-tabs"]/div'
        divs = browser.find_elements(By.XPATH, divs_xpath)
        shipping_div = divs[3]  # shipping tab
        shipping_div.click()
        orders_xpath = '//div[@class="order-list-body"]//div[@class="order-title"]'
        orders = wait.until(EC.presence_of_all_elements_located((By.XPATH, orders_xpath)))
        for order in orders:
            _order_id = order.find_element(By.XPATH, './div[@class="id-btn"]').text
            _order_id = _order_id.split()[-1]
            if _order_id == order_id:
                args = order, message_dict, order_id
                ok = func(*args, **kwargs)
                break
        shipping_div = divs[2]  # To ship tab
        shipping_div.click()
        time.sleep(1)

        return ok

    return inner


class Seller(object):

    def __call__(self, *args, **kwargs):
        self.run()

        # 与下次检测间隔CF.time_interval分钟
        minutes = CF.time_interval
        desc = f'wait {minutes} minutes...'
        short_rest(desc, time_interval=minutes * 60 / 100)

    @tip.register('Detection')
    @TryExcept(not_raise=True)
    def run(self):
        global DETECTION_COUNT
        DETECTION_COUNT += 1
        log_print(f'Start of detection {DETECTION_COUNT}')

        orderid_list = self.search_order_list()
        order_length = len(orderid_list)
        # 刷新页面，遍历订单
        for index in range(order_length):
            if index > 0:
                browser.get(SEARCH_URL)

            orders = wait.until(EC.presence_of_all_elements_located((By.XPATH, '//a[@class="order-item"]')))

            # 遍历订单列表，寻找在待售卖的订单ID列表中的订单
            for order in orders:
                temp_order_id = order.find_element(By.XPATH, './/div[@class="header-desc"]').text.strip()

                # 若该订单ID不在待售卖的订单ID列表中，则跳过
                if temp_order_id not in orderid_list:
                    continue

                # 获取订单详情
                product_dict, order_id = self.get_order_details(order, index)

                # 获取卡密,若卡密不能存在则跳过
                message_dict = TxtControl.get_text(product_dict)
                if message_dict is False:
                    print('Txt files failed to match or the number of cards is insufficient.')
                    continue

                # 售货
                ok = self.ship(order, order_id)

                # 若售货失败,则跳过
                if not ok:
                    continue

                # 发送卡密
                ok = self.chat(order, message_dict, order_id)

                # 若发送卡密成功，则在txt文件中删除卡密
                if ok is True:
                    TxtControl.delete_secret(message_dict)

                orderid_list.remove(temp_order_id)
                print('**********************************************************************')
                break

    @staticmethod
    def search_order_list():
        """获取订单ID列表"""

        orderid_list = []
        print('Getting order list information, please wait.....')
        browser.get(SEARCH_URL)
        try:
            orders = wait.until(EC.presence_of_all_elements_located((By.XPATH, '//a[@class="order-item"]')))

            for order in orders:
                sell_button_xpath = './/div[@class="shopee-popover__ref"]/button'
                sell_button = order.find_element(By.XPATH, sell_button_xpath)
                if sell_button.text.lower().strip() != 'ship':
                    continue

                order_id_xpath = './/div[@class="header-desc"]'
                order_id = order.find_element(By.XPATH, order_id_xpath).text.strip()
                orderid_list.append(order_id)
            print(f'Total number of current orders:{len(orderid_list)}.')
            print(f'Order ID List:{", ".join(orderid_list)}')
        except:
            print('Total number of current orders: 0, no new orders yet!')
            logger.warn(f'Unsuccessful order list:', exc_info=True)
            return orderid_list

        # 跳过tip
        tip2 = browser.find_elements(By.XPATH, '//div[@class="btn-skip"]')
        if len(tip2):
            print('skipping tip2...')
            browser.execute_script("arguments[0].click();", tip2[0])

        return orderid_list

    @staticmethod
    def get_order_details(order: WebElement, index: int):
        """获取订单详情，id、name等"""

        product_dict = {}  # 存储商品信息

        # 获取订单详情
        user_name_xpath = './/div[@class="username text-overflow"]'
        user_name = order.find_element(By.XPATH, user_name_xpath).text.strip()
        order_id_xpath = './/div[@class="header-desc"]'
        order_id = order.find_element(By.XPATH, order_id_xpath).text.strip()
        order_id = order_id.split()[-1]
        product_list_xpath = './/div[@class="order-product-wrapper normal-wrapper"]'
        product_list = order.find_elements(By.XPATH, product_list_xpath)

        for product in product_list:
            product_name_xpath = './/div[@class="ct-item-product-info"]'
            product_name = product.find_element(By.XPATH, product_name_xpath).text.split('\n')[0]

            try:
                product_norm_xpath = './/div[@class="ct-item-meta"]'
                product_norm = product.find_element(By.XPATH, product_norm_xpath).text
                product_norm = product_norm.split(':')[1].strip()
            except:
                product_norm = ''

            product_num = './/div[@class="ct-item-product-num"]'
            product_num = order.find_element(By.XPATH, product_num).text.strip()
            product_info = (product_name + '??' + product_norm) if product_norm else product_name
            product_dict.setdefault(product_info, product_num)

        # 打印订单详情表格
        pretty = PrettyTable()
        pretty.field_names = [f'(No.{index + 1})Order_ID', 'product_name', 'product_norm', 'product_num', 'user_name']
        for key, value in product_dict.items():
            name, norm = key.split('??') if '??' in key else (key, '')
            pretty.add_row([order_id, name, norm, value, user_name])
        print(pretty)

        return product_dict, order_id

    @staticmethod
    def ship(order: WebElement, order_id: str):
        """出售商品"""

        wait_ = WebDriverWait(browser, 15)
        sell_button_xpath = './/div[@class="shopee-popover__ref"]/button'
        sell_button = order.find_element(By.XPATH, sell_button_xpath)
        browser.execute_script("arguments[0].click();", sell_button)
        inputs_xpath = '//div[@class="shopee-input full-width"]//input'
        inputs = wait_.until(EC.presence_of_element_located((By.XPATH, inputs_xpath)))
        tracking_number = ''.join(choices('ABCDEFGHIJKLMNOPQRSTUVWXYZ', k=6)) + str(random()).strip('0.')
        inputs.send_keys(tracking_number)
        xpath = '//div[@class="shopee-modal__footer-buttons"]/button[@class="shopee-button shopee-button--primary shopee-button--normal"]'
        ship_button = browser.find_element(By.XPATH, xpath)
        browser.execute_script("arguments[0].click();", ship_button)

        short_rest()
        print(f'Order ID:{order_id}|tracking number:{tracking_number} Shipped!')

        return True

    @staticmethod
    @into_shipping
    def chat(order: WebElement, message_dict: dict, order_id: str):
        """进入聊天框,发送卡密"""

        chat_xpath = './/div[@class="actions chat-solid mini-chat"]'
        chat = order.find_element(By.XPATH, chat_xpath)
        browser.execute_script("arguments[0].click();", chat)
        textarea = wait.until(EC.presence_of_element_located((By.XPATH, '//textarea')))
        for mes_key, mes_value in message_dict.items():
            for secret in mes_value:
                message = f'{mes_key}: {secret}'
                textarea.send_keys(message)
                ActionChains(browser).key_down(Keys.ENTER).perform()
                time.sleep(5)
                flag = True
                for i in range(1, 6):
                    histories = browser.find_elements(By.XPATH, '//pre')
                    if message.strip() in ' '.join([item.text for item in histories]):
                        flag = False
                        break
                    print(f'Attempting {i} resend:{message}')
                    textarea.send_keys(message)
                    ActionChains(browser).key_down(Keys.ENTER).perform()
                    time.sleep(5)
                if flag:
                    print('Failed to send message. Please check the network.....')
                    return False
        textarea.send_keys(CF.peroration)
        ActionChains(browser).key_down(Keys.ENTER).perform()
        short_rest()
        print(f'Order ID:{order_id}|message:{message_dict} Sent!')
        wrapper_xpath = '//i[@class="GHUxSkxNuJ uhPpW_bDvZ X8XVK1EpGd"]'
        wrapper = browser.find_element(By.XPATH, wrapper_xpath)
        wrapper.click()

        return True


sell = Seller()
